home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
sndpas.zip
/
SOUNDER.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1992-12-22
|
9KB
|
288 lines
{Sound generation and timing interrupt
Written by:
Nels Anderson
92 Bishop Drive
Framingham, MA 01701
Released to the public domain
}
unit Sounder;
interface
Uses
Crt;
procedure StartSound(Notes: POINTER; Repeats: INTEGER; Speed: BYTE);
const
{ Notes Values:
Use these constants to get the proper values for notes. The first
character is the note name, S indicates a sharp, and the final number
indicates the octave.}
CN3 = 13;
CS3 = 14;
DN3 = 15;
DS3 = 16;
EN3 = 16;
FN3 = 17;
FS3 = 19;
GN3 = 20;
GS3 = 21;
AN3 = 22;
AS3 = 23;
BN3 = 25;
CN4 = 26;
CS4 = 28;
DN4 = 29;
DS4 = 31;
EF4 = 31;
EN4 = 33;
FF4 = 33; {?}
FN4 = 35;
FS4 = 37;
GN4 = 39;
GS4 = 42;
AF4 = 42;
AN4 = 44;
AS4 = 47;
BF4 = 47;
BN4 = 49;
CN5 = 52;
CS5 = 55;
DF5 = 55;
DN5 = 59;
DS5 = 62;
EN5 = 66;
FN5 = 70;
FS5 = 74;
GN5 = 78;
GS5 = 83;
AF5 = 83;
AN5 = 88;
AS5 = 93;
BF5 = 93;
BN5 = 99;
CN6 = 105;
CS6 = 111;
DN6 = 117;
DS6 = 124;
EN6 = 133;
FN6 = 140;
FS6 = 148;
GN6 = 157;
GS6 = 166;
AN6 = 176;
AS6 = 186;
BN6 = 198;
CN7 = 209;
CS7 = 222;
DN7 = 235;
DS7 = 249;
{ Sound Collection:
Each sound is an array of pairs of bytes, where the first byte of each
pair is the duration in 1/18th second units and the second byte of the
pair is the note frequency in 10's of Hertz. To use a sound, include
a command like the following in a program:
StartSound(@PhaserSound,3,1); {do phaser sound 3 times}
Ruddigore: array[1..411] of BYTE = ( {theme song}
36,000,
3,DN4,1,DN4, 2,DN4,2,DN4,8,FN4,4,DN4,
2,DN4,2,DN4,8,AN4,3,AN4,1,AN4,
4,DN5,2,AN4,2,AN4,4,AN4,4,BN4, 12,CN5,4,CN4,
2,CN4,2,CN4,8,EN4,2,CN4,2,CN4,
2,CN4,2,CN4,8,GN4,4,CN4, 4,CN5,2,CN5,2,CN5,2,CN5,2,DF5,4,BF4,
12,AF4,3,AF4,1,AF4,
4,FF4,4,FF4,6,AF4,2,FF4, 4,EF4,4,EF4,6,AF4,2,AF4,
4,FF4,4,FF4,4,AF4,2,AF4,2,AF4, 12,BN4,4,EN4,
4,AN4,4,AN4,4,AN4,2,BN4,2,CS5,
4,DN5,4,AN4,4,FN4,4,DN4, 4,AN4,4,AN4,4,AN4,2,BN4,2,CS5,
6,DN5,2,FN5,4,FN5,4,DN5, 4,DN5,2,DN5,2,DN5,4,CS5,4,CS5,
6,DN5,2,FN5,4,FN5,4,DN5, 4,DN5,4,CS5,4,CN5,4,AF4,
4,CN5,4,BN4,4,BF4,4,GN4, 4,CS5,4,AN4,4,FS4,4,FN3,
8,AN4,8,AN3, 8,DN4,8,000,
3,DN4,1,DN4, 2,DN4,2,DN4,8,FN4,4,DN4,
2,DN4,2,DN4,8,AN4,3,AN4,1,AN4,
4,DN5,2,AN4,2,AN4,4,AN4,4,BN4, 12,CN5,4,CN4,
2,CN4,2,CN4,8,EN4,2,CN4,2,CN4,
2,CN4,2,CN4,8,GN4,4,CN4, 4,CN5,2,CN5,2,CN5,2,CN5,2,DF5,4,BF4,
12,AF4,3,AF4,1,AF4,
4,FF4,4,FF4,6,AF4,2,FF4, 4,EF4,4,EF4,6,AF4,2,AF4,
4,FF4,4,FF4,4,AF4,2,AF4,2,AF4, 12,BN4,4,EN4,
4,AN4,4,AN4,4,AN4,2,BN4,2,CS5,
4,DN5,4,AN4,4,FN4,4,DN4, 4,AN4,4,AN4,4,AN4,2,BN4,2,CS5,
6,DN5,2,FN5,4,FN5,4,DN5, 4,DN5,2,DN5,2,DN5,4,CS5,4,CS5,
6,DN5,2,FN5,4,FN5,4,DN5, 4,DN5,4,CS5,4,CN5,4,AF4,
4,CN5,4,BN4,4,BF4,4,GN4, 4,CS5,4,AN4,4,FS4,4,FN3,
8,AN4,8,AN3,
4,DN4,2,000,2,GN3,4,DN4,2,000,2,GN3,
4,DN4,2,000,2,GN3,2,DN4,2,GN3,2,DN4,2,GN3,
4,DN4,4,000,4,DN4,4,000, 16,DN4,0);
Canon: array[1..639] of BYTE = (
36,000,
4,000,4,FS5,4,EN5,4,DN5, 4,EN5,4,DN5,4,CS5,8,BN4, {1-2}
4,FS5,4,EN5,4,DN5,4,DN5, 4,CS5,4,BN4,4,AN4,4,CS5, {3-4}
4,000,4,BN5,4,AN5,4,GN5, 8,AN5,4,BN5,4,CS6, {5-6}
8,DN6,8,BN5, 4,FS5,4,EN5,4,FS5,2,AN4,2,GN4, {7-8}
4,FS5,4,EN5,4,FS5,4,AN5, 8,FS5,4,FS5,4,EN5, {9-10}
4,DN5,2,DN5,2,EN5,4,FS5,4,BN5, 8,BN5,4,000,4,AN5, {11-12}
4,GN5,2,FS5,2,EN5,4,DN5,4,EN4, 4,FS4,4,000,4,DN5,4,FS4,
4,GN4,4,DN5,4,EN5,4,DN5, 2,CS5,2,BN4,8,AN4,4,000, {15-16}
2,FS4,2,AN4,2,FS4,2,AN4,2,FS4,2,AN4,2,FS4,2,AN4, {17}
2,EN4,2,AN4,2,EN4,2,AN4,2,EN4,2,AN4,2,EN4,2,AN4, {18}
2,FS4,2,BN4,2,FS4,2,BN4,2,FS4,2,BN4,2,FS4,2,AN4, {19}
2,AN4,2,CS5,2,FS5,2,GN5,2,FS5,2,DN5,2,AN4,2,CS5, {20}
2,AN4,4,DN5,4,GN5,2,DN5,2,CS5,2,BN4, {21}
2,DN5,2,CS5,8,DN5,4,DN5, {22}
2,DN4,2,BN4,2,CS5,2,BN4,4,DN5,2,EN5,2,DN5, {23}
2,CS5,2,BN4,8,AN4,2,EN4,2,AN4, {24}
4,FS5,4,DN5,4,FS4,4,FS5, {25}
4,EN5,4,AN4,1,EN5,1,FS5,1,EN5,1,FS5,1,EN5,1,FS5,2,EN5,
4,DN5,4,BN4,4,FS4,4,DN5, {27}
4,CS5,4,AN4,1,CS5,1,DN5,1,CS5,1,DN5,1,CS5,1,BN4,2,CS5,{28}
4,BN4,4,DN5,4,BN4,4,GN4, {29}
1,FS4,1,AN4,1,DN5,1,FS5,1,AN4,1,DN5,1,FS5,1,AN5, {30}
1,DN5,1,FS5,1,AN5,1,BN5,1,AN5,1,GN5,1,FS5,1,EN5,
4,DN5,4,BN4,2,GN4,2,BN4,2,CS5,2,DN5, {31}
4,CS5,4,EN5,1,AN5,1,BN5,1,AN5,1,BN5,1,AN5,1,BN5,2,GN5,{32}
1,FS5,1,EN5,1,DN5,1,AN4,1,FS4,1,EN4,1,BN4,1,AN3, {33}
1,DN6,1,GN5,1,FS5,1,DN5,1,AN4,1,GN4,1,FS4,1,DN4,
1,EN5,1,DN5,1,CS5,1,BN4,1,CS5,1,GN4,1,FS4,1,EN4, {34}
1,GN5,1,FS5,1,EN5,1,DN5,1,CS5,1,BN4,1,AN4,1,GN4,
1,DN5,1,CS5,1,BN4,1,FS4,1,DN4,1,CS4,1,BN3,1,FS3, {35}
1,BN5,1,EN5,1,DN5,1,CS5,1,BN4,1,AN4,1,GN4,1,FS4,
1,CS5,1,BN4,1,AN4,1,GN4,1,AN4,1,EN4,1,DN4,1,CS4, {36}
1,AN5,1,GN5,1,FS5,1,EN5,1,DN5,1,CS5,1,BN4,1,AN4,
1,BN4,1,AN4,1,GN4,1,FS4,1,FS4,1,DN4,1,CS4,1,BN3, {37}
1,GN4,1,BN4,1,CS5,1,DN5,1,GN5,1,AN5,1,BN5,1,DN6,
1,FS6,1,EN6,1,DN6,1,AN5,1,FS5,1,EN5,1,DN5,1,AN4, {38}
1,DN5,1,EN5,1,FS5,1,GN5,1,AN5,1,BN5,1,CS6,1,DN6,
1,GN5,1,FS5,1,EN5,1,DN5,1,CS5,1,BN4,1,AN4,1,GN4, {39}
1,BN5,1,AN5,1,GN5,1,FS5,1,EN5,1,DN5,1,CS5,1,BN4,
1,CS6,1,BN5,1,AN5,1,GN5,1,FS5,1,EN5,1,DN5,1,CS5, {40}
1,AN4,1,GN4,1,FS4,1,EN4,1,DN4,1,CS4,1,BN3,1,AN3,
8,DN5,8,AN4, 8,CS5,8,AN4, 8,BF4,8,FN4,
8,BF4,4,000,4,BF4, 8,BF4,8,AN4, 16,AN4,16,DN5,0);
PhaserSound: array[1..5] of BYTE = (
1,30,1,31,0);
TorpSound: array[1..13] of BYTE = (
1,8,1,9,1,8,1,20,1,21,1,22,0);
WhistleSound: array[1..5] of BYTE = (
4,50,10,100,0);
Type
{
You must modify the number 639 below so that
it equals the number of cells in the biggest
array of the Sound Collection constants above.
}
ByteArray = array[1..639] of BYTE;
Var
SoundSpeed: BYTE; {multiplier used to slow down sounds}
SoundCount: BYTE; {counts how long current sound has been on}
MySound: ^ByteArray; {points to array of notes and durations}
New1CInt, {address of new interrupt}
Int1CSave: POINTER; {saves original $1C interrupt}
NumRepeats, {number of times to repeat sound}
MyClock, {general purpose timer}
SoundOff: INTEGER; {offset into note array}
SndFlg, {set when sounds allowed}
MakeSound: BOOLEAN; {set while sound is going}
implementation
procedure StartSound(Notes: POINTER; Repeats: INTEGER; Speed: BYTE);
{ Start generating the sound pointed to by Notes }
begin
SoundSpeed := Speed; {set speed}
SoundOff := 1; {offset into sound array}
SoundCount := 1; {counter for current note}
MySound := Notes; {pointer to sound array}
MakeSound := TRUE; {enable sounds}
NumRepeats := Repeats; {number times to repeat sound}
end; {StartSound procedure}
procedure TimerInt;
interrupt;
{ Clock tick interrupt
BIOS interrupt $1C has been replaced with the following routine. This
interrupt occurs on each clock tick (18 per second).
The interrupt mainly handles sounds. When the MakeSound flag is true,
the pointer MySound must be pointing to a byte array containing durations
and frequencies of sounds to be generated. Sounds will be generated from
the array until a duration of 0 is found.
A general purpose timer is also incremented each time the interrupt
occurs.
To use the interrupt, the main program needs to do the following:
Begin
GetIntVec($1C,Int1CSave); (save original interrupt vector)
SetIntVec($1C,New1CInt); (install timer interrupt)
.
. (body of program)
.
StartSound(@PhaserSound,3,1); (phaser sound 3 times, normal speed)
.
. (body of program)
.
SetIntVec($1C,Int1CSave); (restore original 1C interrupt)
end.
}
begin
Inc(MyClock); {increment timer}
if not SndFlg then begin {exit if sounds turned off}
MakeSound := FALSE;
Exit;
end;
if MakeSound then begin {if making a sound...}
Dec(SoundCount);
if SoundCount <= 0 then begin {if current sound done...}
NoSound;
SoundCount := SoundSpeed * MySound^[SoundOff];{get duration of next one}
if SoundCount > 0 then begin {if there is a next one...}
Inc(SoundOff);
Sound(10*MySound^[SoundOff]); {start it up}
Inc(SoundOff);
end
else begin {if end of sound array...}
Dec(NumRepeats); {decrement number of repeats}
if NumRepeats > 0 then begin {if we must repeat...}
SoundOff := 3; {reset offset into array}
SoundCount := MySound^[1]; {get duration of first note}
Sound(10*MySound^[2]); {start it up}
end
else begin {if all repeats now done...}
NoSound; {stop all sound}
MakeSound := FALSE; {reset flag}
end;
end;
end; {if SoundCount = 0}
end; {if making a sound}
end; {TimerInt interrupt procedure}
begin
SndFlg := TRUE; {sounds are allowed}
MakeSound := FALSE; {sound initially off}
MyClock := 0; {reset timer}
New1CInt := @TimerInt; {get address of interrupt}
end.